package cn.edu.scnu.lastandroid.logic

import androidx.lifecycle.liveData
import cn.edu.scnu.lastandroid.logic.dao.PlaceDao
import cn.edu.scnu.lastandroid.logic.model.Place
import cn.edu.scnu.lastandroid.logic.model.Weather
import cn.edu.scnu.lastandroid.logic.network.WeatherNetWork
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlin.coroutines.CoroutineContext

object Repository {
    fun searchPlaces(query: String) = fire(Dispatchers.IO) {
        val placeResponse = WeatherNetWork.searchPlaces(query)
        if (placeResponse.status == "200") {
            val places = placeResponse.location
            Result.success(places)
        } else {
            Result.failure(RuntimeException("response status is ${placeResponse.status}"))
        }
    }

    /**
     * 按照城市刷新天气
     */
    fun refreshWeather(city: String) = fire(Dispatchers.IO) {
        coroutineScope {
            val deferredRealtime = async {
                WeatherNetWork.getRealtimeWeather(city)
            }
            val deferredDaily = async {
                WeatherNetWork.getDailyWeather(city)
            }
            val deferredLife = async {
                WeatherNetWork.getLifeResponse(city)
            }
            val deferredAQI = async {
                WeatherNetWork.getAQI(city)
            }
            val realtimeResponse = deferredRealtime.await()
            val dailyResponse = deferredDaily.await()
            val lifeResponse = deferredLife.await()
            val aqiResponse = deferredAQI.await()
            if (realtimeResponse.code == "200" && dailyResponse.code == "200") {
                val weather = Weather(
                    realtimeResponse.now,
                    dailyResponse.daily,
                    lifeResponse.daily,
                    aqiResponse.now
                )
                Result.success(weather)
            } else {
                Result.failure(RuntimeException("realtime response status is ${realtimeResponse.code}" + "daily response status is ${dailyResponse.code}"))
            }
        }
    }

    /**
     * 按照经纬度刷新天气
     */
    fun refreshWeather(lng: String, lat: String) = fire(Dispatchers.IO) {
        coroutineScope {
            val deferredRealtime = async {
                WeatherNetWork.getRealtimeWeather(lng, lat)
            }
            val deferredDaily = async {
                WeatherNetWork.getDailyWeather(lng, lat)
            }
            val deferredLife = async {
                WeatherNetWork.getLifeResponse(lng, lat)
            }
            val deferredAQI = async {
                WeatherNetWork.getAQI(lng, lat)
            }
            val realtimeResponse = deferredRealtime.await()
            val dailyResponse = deferredDaily.await()
            val lifeResponse = deferredLife.await()
            val aqiResponse = deferredAQI.await()
            if (realtimeResponse.code == "200" && dailyResponse.code == "200") {
                val weather = Weather(
                    realtimeResponse.now,
                    dailyResponse.daily,
                    lifeResponse.daily,
                    aqiResponse.now
                )
                Result.success(weather)
            } else {
                Result.failure(RuntimeException("realtime response status is ${realtimeResponse.code}" + "daily response status is ${dailyResponse.code}"))
            }
        }
    }

    private fun <T> fire(context: CoroutineContext, block: suspend () -> Result<T>) =
        liveData<Result<T>>(context) {
            val result = try {
                block()
            } catch (e: Exception) {
                Result.failure<T>(e)
            }
            emit(result)
        }

    /**
     * 保存地址
     */
    fun savePlace(place: Place) = PlaceDao.savePlace(place)

    /**
     * 获取地址
     */
    fun getSavedPlace() = PlaceDao.getSavedPlace()

    /**
     * 是否保存了地址
     */
    fun isPlaceSaved() = PlaceDao.isPlaceSaved()
}